package model

import (
	"gitee.com/lllgo/gopkg/csv"
	"gitee.com/lllgo/opsctl/pkg/tools"
	"strings"
)

// 存储机器上安装的软件和服务
type Tag struct {
	IP   string
	Name string
	Tags string
}

// 创建tag对象 同时与数据库同步 保证数据是最新的
func SaveTag(hostName, ip, tag string) (Tag, error) {
	tmpRs, tmpMs := getTagByNameAndIp(hostName, ip)
	if len(tmpRs) > 0 {
		tmp := tmpRs[0].(Tag)
		tmp.Tags = addTag(tmp.Tags, tag)
		err := tagTable.SetRecordById(tmp, tmpMs[0].Id)
		return tmp, err
	} else {
		t := Tag{Name: hostName, IP: ip, Tags: tag}
		err := tagTable.Insert(t)
		return t, err
	}

}

// 创建tag对象 同时与数据库同步 保证数据是最新的
func DeleteTag(hostName, ip, tag string) error {
	tmpRs, tmpMs := getTagByNameAndIp(hostName, ip)
	if len(tmpRs) > 0 {
		tmp := tmpRs[0].(Tag)
		tmp.Tags = removeTag(tmp.Tags, tag)
		return tagTable.SetRecordById(tmp, tmpMs[0].Id)
	}
	return nil
}

func getTagByNameAndIp(hostName, ip string) ([]csv.Record, []csv.Meta) {
	return tagTable.GetRecordsAndMeta(func(r csv.Record, m csv.Meta) bool {
		t := r.(Tag)
		return t.Name == hostName && t.IP == ip
	})
}

func GetTags(tags ...string) []Tag {
	return getTags(tags, nil)
}

func getTags(tags []string, hs []tools.Host) (ts []Tag) {
	rs := tagTable.GetRecords(func(r csv.Record, m csv.Meta) bool {
		tmpTag := r.(Tag).Tags
		tmpIP := r.(Tag).IP

		//按tag模糊匹配
		if len(tags) > 0 {
			for _, t := range tags {
				if t != "" {
					if strings.Contains(tmpTag, t) {
						return true
					}
				}
			}
			return false
		}

		//按IP精确匹配
		if len(hs) > 0 {
			for _, host := range hs {
				if host.IP() == tmpIP {
					return true
				}
			}
			return false
		}

		return true
	})

	for _, r := range rs {
		ts = append(ts, r.(Tag))
	}

	return
}

func GetTagsByHost(hs ...tools.Host) []Tag {
	return getTags(nil, hs)
}

func addTag(oldTag, tag string) string {
	if oldTag == "" {
		return tag
	} else if !strings.Contains(oldTag, tag) {
		return oldTag + "," + tag
	}
	return oldTag
}

func removeTag(oldTag, tag string) string {
	return strings.Trim(strings.ReplaceAll(strings.ReplaceAll(oldTag, tag, ""), ",,", ","), ",")
}
